package com.globalwave.report.template.excel;

import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;

public class Row {

	final public static short MERGE_STATUS_NA=0;
	final public static short MERGE_STATUS_STARTING=1;
	final public static short MERGE_STATUS_STARTED=2;
	final public static short MERGE_STATUS_ENDING=3;
	
	private HSSFRow _row ;
	private ExcelTemplate template ;
	private Cell firstCell ;
	private boolean isListRow = false ;
	private int listSize = 0 ;
	private String listName = null ;
	private short mergeStatus = 0 ;
	private String mergeRefCol ;
	private int mergeStartRowNum = 0 ;
	
	public Row(HSSFRow _row, ExcelTemplate template) {
		this._row = _row ;
		this.template = template ;
	}

	
	public void precompile() {
		
		Cell preview = null ; 
		Cell current = null ; 
		
		int lastCellNum = _row.getLastCellNum() ;
		
		for (int cellIndex = 0 ; cellIndex <= lastCellNum ; cellIndex ++) {
			HSSFCell _cell = _row.getCell(cellIndex) ;
			if (_cell == null) {
				continue ;
			}
			preview = current ;
			current = new Cell(_cell, this) ;
			current.precompile();
			
			if (!isListRow && current.isListCell()) {
				isListRow = true ;
			}
			
			if (preview != null) {
				preview.setNext(current) ;
			}
			
			if (firstCell == null){
				firstCell = current ;
			}
		}
	}
	
	public void compile() throws Exception {
		if (isListRow) {
			Map<String, Object> c = this.template.getContext() ;
			List<Object> list = (List<Object>)c.get(listName) ;
			listSize = list.size() ;
			for (int i = 0 ; i < listSize ; i ++) {
				
				c.put(listName + "$item", list.get(i)) ;
				
			    insert() ;
			    
			    if (isMergeEnding()) {
			    	this.mergeStatus = MERGE_STATUS_STARTING ;
			    	this.mergeStartRowNum = this._row.getRowNum() - 1 ;
			    } else if (isMergeStarting() || isMergeStarted()) {
			    	this.mergeStatus = MERGE_STATUS_STARTED ;
			    	if (i + 1 < listSize) {
			    		if (!isEqual(list.get(i), list.get(i+1), mergeRefCol)){
			    			this.mergeStatus = MERGE_STATUS_ENDING ;
			    		}
			    	} else {
			    		this.mergeStatus = MERGE_STATUS_ENDING ;
			    	}
			    }// else is no merge
				complieCells() ;
			    if (isMergeStarting() && i + 1 < listSize) {
		    		if (!isEqual(list.get(i), list.get(i+1), mergeRefCol)){
		    			this.mergeStatus = MERGE_STATUS_ENDING ;
		    		}
		    	}
			}
			//_row.getSheet().removeRow(_row) ;// 删除映射列
			delete();
		} else {
			complieCells() ;
		}
	}
	
	private boolean isEqual(Object bean1, Object bean2, String p) {
		try {
			String v1 = BeanUtils.getProperty(bean1, p) ;
			String v2 = BeanUtils.getProperty(bean2, p) ;
			if (v1 == null && v2 == null) {
				return true ;
			} else if (v1 != null){
				return v1.equals(v2) ;
			} else {
				return v2.equals(v1) ;
			}
		} catch (Exception e) {
			return false ;
		}
	}
	
	private void insert() throws Exception {
		// current row往下移
        //HSSFRow newRow = _row.getSheet().createRow(_row.getRowNum()) ;
		int currentRowNum = _row.getRowNum() ;
		
		HSSFSheet _sheet = _row.getSheet() ;
		
		_sheet.shiftRows(currentRowNum, _sheet.getLastRowNum(), 1, true, false);
        
		HSSFRow newRow = _sheet.getRow(currentRowNum) ;
        _row = _sheet.getRow(currentRowNum + 1) ;
        
        
        int lastCellNum = _row.getLastCellNum() ;
        for (int i=0 ; i <= lastCellNum ; i ++ ) {
        	HSSFCell c = _row.getCell(i) ;
        	if (c != null) {
        		HSSFCell newC = newRow.createCell(i) ;
        		newC.setCellComment(c.getCellComment()) ;
        		//newC.setCellFormula(c.getCellFormula()) ;
        		newC.setCellStyle(c.getCellStyle()) ;
        		newC.setCellType(c.getCellType()) ;
            	if(newC.getCellType() == HSSFCell.CELL_TYPE_NUMERIC) {
            		newC.setCellValue(c.getNumericCellValue()) ;
            	} else if(newC.getCellType() == HSSFCell.CELL_TYPE_STRING) {
            		newC.setCellValue(c.getStringCellValue()) ;
            	}
        	}
        }
        /*
		Cell current = firstCell ;
		while (current != null) {
			current.resetToNextRowCell() ;
			current = current.getNext() ;
		}*/
	}
	private void delete() throws Exception {
		// current row往下移
        //HSSFRow newRow = _row.getSheet().createRow(_row.getRowNum()) ;
		int currentRowNum = _row.getRowNum() + 1;
		
		HSSFSheet _sheet = _row.getSheet() ;
		
		if (currentRowNum <= _sheet.getLastRowNum()) {
	    	_sheet.shiftRows(currentRowNum, _sheet.getLastRowNum(), -1, true, false);
		} else {
		    _sheet.removeRow(_row) ;
		}
	}
	
	private void complieCells() throws Exception {
		Cell current = firstCell ;
		while (current != null) {
			current.compile() ;
			current = current.getNext() ;
		}
	}
	
	public ExcelTemplate getTemplate() {
		return template;
	}
	public void setListName(String listName) {
		this.listName = listName;
	}
	public int getListSize() {
		return listSize;
	}
	public void setMergeStarting(String mergeRefCol) {
		if (this.mergeStatus == MERGE_STATUS_ENDING) {
			return ;
		}
		this.mergeRefCol = mergeRefCol ;
		this.mergeStatus = MERGE_STATUS_ENDING ;
	}
	public short getMergeStatus() {
		return mergeStatus;
	}
	public int getMergeStartRowNum() {
		return mergeStartRowNum;
	}

	public boolean isMergeStarting() {
		return this.mergeStatus == MERGE_STATUS_STARTING ;
	}
	public boolean isMergeStarted() {
		return this.mergeStatus == MERGE_STATUS_STARTED ;
	}
	public boolean isMergeEnding() {
		return this.mergeStatus == MERGE_STATUS_ENDING ;
	}
}
